import requests, time, base64, json, rsa, re, binascii
from urllib import parse


class Weibologin():
    def __init__(self, user, password):
        self.user = user
        self.password = password
        self.sess = requests.session()
        self.headers = {
            'Referer': 'https://weibo.com/',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0'
        }

    def pre_login(self):
        # 构造参数
        params = {
            'entry': 'weibo',
            'callback': 'sinaSSOController.preloginCallBack',
            'su': base64.b64encode(parse.quote(self.user).encode()).decode(),  # parse.quote有个函数可以处理特色符号@
            'rsakt': 'mod',
            'client': 'ssologin.js(v1.4.19)',
            '_': int(time.time() * 1000)
        }
        url = 'https://login.sina.com.cn/sso/prelogin.php'
        # 发起prelogin请求
        r = self.sess.get(url, params=params)
        start = r.text.index('{')
        end = r.text.index('}')
        # 获取登录所需参数
        dc = json.loads(r.text[start:end + 1])
        print('dc:', dc)
        return dc

    def login(self, dc):
        # 构造登录请求所需数据
        data = {
            'entry': 'weibo',
            'gateway': '1',
            'from': '',
            'savestate': '7',
            'qrcode_flag': 'false',
            'useticket': '1',
            'pagerefer': '',
            'vsnf': 1,
            'su': base64.b64encode(parse.quote(self.user).encode()).decode(),
            'service': 'miniblog',
            'servertime': dc['servertime'],
            'nonce': dc['nonce'],
            'pwencode': 'rsa2',
            'rsakv': dc['rsakv'],
            'sp': '',
            'sr': '1920x1080',
            'encoding': 'UTF-8',
            'prelt': 34,
            'url': 'https://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&sudaref=weibo.com&display=0&retcode=101&reason=%B5%C7%C2%BC%C3%FB%BB%F2%C3%DC%C2%EB%B4%ED%CE%F3',
            'returntype': 'META'
        }
        # 构造非对称密钥
        pubkey_arg = dc['pubkey']
        pubkey = rsa.PublicKey(int(pubkey_arg, 16), int('10001', 16))
        sp = rsa.encrypt(('\t'.join((str(dc['servertime']), dc['nonce'])) + '\n' + self.password).encode(), pubkey)
        # 去掉加密结构的字节码中的'\x'，转换成字符串
        sp = binascii.b2a_hex(sp).decode()
        data['sp'] = sp
        print('sp:', data['sp'])
        r = self.sess.post('https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19)', data=data)
        r.encoding = 'gbk'
        print('r:', r.text)
        # 获取重定向的验证url
        location_replace_url = re.search(r'location\.replace\("(.+)"\)', r.text).group(1)
        print('location_replace_url:',location_replace_url)
        return location_replace_url

    def get_cookie(self, url):
        r = self.sess.get(url)
        r.encoding = 'gbk'
        print('r:', r.text)
        ls = re.search('"arrURL":(.+?)}', r.text).group(1)
        print('ls:', ls)
        ls.replace('\\', '')
        print('ls:', ls)
        ls = json.loads(ls)
        for url in ls:
            self.sess.get(url)
        print('cookie:', self.sess.cookies)

    def check(self):
        r=self.sess.get('https://weibo.com')
        r.encoding='utf8'
        print('r:',r.text)
        print('登录状态','梦丨华尔兹丿' in r.text)

    def run(self):
        dc = self.pre_login()
        location_replace_url = self.login(dc)
        self.get_cookie(location_replace_url)
        self.check()



w = Weibologin('18859117071', 'extreme')
w.run()
